#include "Student.h"

Student::Student(Database dBase) : Users (dBase) {

}

void Student::studentMenu () {

	int choice;
	bool badSelection = false;

	cout << "Welcome to A-Star Global! " << endl 
		 << "Hi, " << fullName << "!" << endl << endl;

	getAnnouncement();

	do {
		badSelection = false;
		cout << "My Menu" << endl 
			 << "===========================" << endl << endl;
		cout << "1. Show Timetable" << endl 
			 << "2. Attendance Record" << endl
			 << "3. Change Password" << endl
			 << "4. Check E-mails" << endl
			 << "5. Quit" << endl << endl
			 << "Enter your choice: ";

		cin >> choice;
		cin.clear();
		cout << endl;

		switch (choice) {
			case 1: displayClasses();
					press_enter();
				break;
			case 2: attendanceMenu();
				break;
			case 3: changePassword();
					press_enter();
				break;
			case 4 : emailSystem();
				break;
			case 5: cout << "Good Bye!" << endl << endl;
				break;
			default: badSelection = true;
					 cout << endl << "Invalid choice." << endl;
					 press_enter();
				break;
		}
	}while (choice != 5 || badSelection != false);
}

void Student::attendanceMenu() {

	int choice;
	bool badSelection = false;
	do {
		badSelection = false;
		cout << "Attendance Menu" << endl
			 << "---------------" << endl << endl;
		cout << "1. Show absent record" << endl 
			 << "2. Submit reason" << endl 
			 << "3. Submit MC(.pdf)" << endl 
			 << "4. Main Menu" << endl << endl;
		cout << "Enter your choice: ";
		
		cin >> choice;
		cin.clear();
		cout << endl;

		switch (choice) {

			case 1: viewAbsentRecord ();
					press_enter();
					break;
			case 2: stateReason ();
					press_enter();
					break;
			case 3: cout << "MC uploaded ..." << endl;
					press_enter();
					break;
			case 4: cout << "Returning to main menu..." << endl;
					press_enter();
					break;
			default : badSelection = true;
					  cout << "Invalid choice." << endl;
					  press_enter();
					break;
		}
	} while (choice != 4 || badSelection != false);
}

void Student::viewAbsentRecord () {

	vector < vector<string> > absentRecord;
	string statement = "SELECT m.module_code, m.module_name, pt.timeslot ";
	statement += "FROM ABSENTEES a, STUDENTS_LESSONS sl, LESSONS l, MODULES m, PLACE_TIME pt ";
	statement += "WHERE a.sl_id = sl.sl_id AND sl.lessons_id = l.lessons_id AND l.module_code = m.module_code AND l.pt_id = pt.pt_id ";
	statement += "AND a.reasons = '' ";
	statement += "AND sl.fullname = '" + fullName + "';";

	absentRecord = db.query(statement);
	cout << "Displaying Absent Record..." << endl << endl;

	if (absentRecord.size() != 0) {

		cout << setw(15) << left << "Module Code" << setw(40) << left << "Module Name"
			 << setw(18) << left << "Date and Time" << endl;
		cout << "=======================================================================" << endl;

		for (int i = 0; i < absentRecord.size(); i++) {
			vector <string> row = absentRecord [i];

			cout << setw(15) << left << row[0] << setw(40) << left << row[1]
				 << setw(18) << left << row[2] << endl;
		}
	}

	else
		cout << "No records to display..." << endl << endl;

	cout << endl;
}

void Student::stateReason () {

	string inputDate;
	cin.ignore();
	cout << "Enter the date to submit your absent reason (YYYY-MM-DD HH:MM): ";
	getline(cin, inputDate);
	cin.clear();
	cin.sync();


	vector < vector<string> > absentRecord;
	string statement = "SELECT pt.timeslot FROM ABSENTEES a, STUDENTS_LESSONS sl, LESSONS l, MODULES m, PLACE_TIME pt ";
	statement += "WHERE a.sl_id = sl.sl_id AND sl.lessons_id = l.lessons_id AND l.module_code = m.module_code AND l.pt_id = pt.pt_id ";
	statement += "AND strftime ('%Y-%m-%d %H:%M', pt.timeslot) = '" + inputDate + "';";
	absentRecord = db.query(statement);

	if (absentRecord.size() != 0) {
		string reason;
		cout << "Enter your reason: ";
		getline(cin, reason);
		cin.clear();
		cin.sync();

		string reasonStatement = "UPDATE ABSENTEES SET reasons = '" + reason + "' WHERE sl_id = ";
		reasonStatement += "(SELECT a.sl_id FROM ABSENTEES a, STUDENTS_LESSONS sl, LESSONS l, MODULES m, PLACE_TIME pt ";
		reasonStatement += "WHERE a.sl_id = sl.sl_id AND sl.lessons_id = l.lessons_id AND l.module_code = m.module_code AND l.pt_id = pt.pt_id ";
		reasonStatement += "AND sl.fullname = '" + fullName + "' );";
		
		db.query (reasonStatement);

		cout << endl << "Reason uploaded.." << endl;
	}
	else
		cout << "Date does not exists." << endl;
}

void Student::displayClasses() {
	vector < vector<string> > myClasses;
	string statement = "SELECT l.lessons_id, m.module_code, m.module_name, pt.venue, pt.timeslot "; 
	statement += "FROM STUDENTS_LESSONS sl, LESSONS l, MODULES m, PLACE_TIME pt ";
	statement += "WHERE sl.lessons_id = l.lessons_id AND l.module_code = m.module_code AND l.pt_id = pt.pt_id ";
	statement += "AND sl.fullname = '" + fullName + "';";

	myClasses = db.query(statement);
	cout << "Displaying My Classes...." << endl << endl;

	if (myClasses.size() != 0) {
		cout << setw(10) << left << "Lesson" << setw(15) << left << "Module Code"
			 << setw(40) << left << "Module Name" << setw(18) << left << "Venue" 
			 << setw(18) << left << "Date and Time" << endl;
		cout << "=================================================================================================" << endl;

		for (int i = 0; i < myClasses.size(); i++) {
			vector <string> row = myClasses [i];

			cout << setw(10) << left << row[0] << setw(15) << left << row[1]
			 	 << setw(40) << left << row[2] << setw(18) << left << row[3] 
			 	 << setw(18) << left << row[4] << endl;
		}

	}
	else
		cout << "No classes to display..." << endl << endl;

	cout << endl;
}

void Student::changePassword() {

	string newPassword, newPassword2;
	bool valid = false;

	while(!valid) {

		cout << "Enter your new password: ";
		cin >> newPassword;
		cout << "Re-confirm your new password: ";
		cin >> newPassword2;

		valid = checkPassword (newPassword, newPassword2);

		if (valid == true) {
			db.changePassword (newPassword);
			cout << "Password successfully changed.." << endl;
		}
	}
}

bool Student::checkPassword (string pass1, string pass2) {

	bool alphaPresent = false;
	bool numPresent = false;

	if (pass1 == pass2) {

		for (int i = 0; i < pass1.length(); i++) {
			//check if password contain alphabets
			if (isalpha(pass1[i]))
				alphaPresent = true;
			//check if password contain digits
			else if (isdigit(pass1[i]))
				numPresent = true;
			//check if password contain non alphanumeric characters
			else {
				cout << "Invalid character. Please key in again." << endl << endl;
				return 0;
			}
		}
		//if password is valid (contains at least 1 letter and 1 digit)
		if (alphaPresent == true && numPresent == true && pass1.length() >= 8)
			return 1;
		
		else 
			cout << "Password needs to 8 characters long and contain at least 1 digit and 1 letter. Please key in again." << endl << endl;
			return 0;
	}
	//if input password and reconfirmed password is not the same
	else {

		cout << "Password does not match. Please key in again." << endl << endl;
		return 0;
	}

}

void Student::getAnnouncement() {

	cout << "Announcements" << endl 
		 << "=============" << endl << endl;

	vector < vector<string> > Announcements;

	string statement = "SELECT l.module_code, l.notice FROM STUDENTS_LESSONS sl, LESSONS l ";
	statement += "WHERE sl.lessons_id = l.lessons_id AND l.notice != '' AND sl.fullname = '" + fullName + "';";

	Announcements = db.query(statement);

	if (Announcements.size() != 0) {
		for (int i = 0; i < Announcements.size(); i++) {
			vector <string> row = Announcements[i];
			cout << row[0] << endl << "-----------" << endl;
			cout << row[1] << endl << endl;
		}
	}
	else
		cout << "No announcement to display..." << endl << endl;
}

void Student::emailSystem() {

	int choice;
	bool badSelection = false;

	do {
		badSelection = false;
		cout << "E-mail Menu" << endl
			 << "-----------" << endl << endl;

		cout << "1. Display all mails" << endl
			 << "2. Delete mails" << endl
			 << "3. Main Menu" << endl << endl;
		cout << "Enter your choice: ";
		
		cin >> choice;
		cin.clear();
		cout << endl;

		switch (choice) {

			case 1: displayMails();
					press_enter();
					break;
			case 2: deleteMails();
					press_enter();
					break;
			case 3: cout << "Returning to main menu..." << endl;
					press_enter();
					break;
			default : badSelection = true;
					  cout << "Invalid choice." << endl;
					  press_enter();
					  break;
		}

	}while (choice != 3 || badSelection != false);
}

void Student::displayMails() {

	vector < vector<string> > myMails;
	string statement = "SELECT mail_id, mail FROM EMAILS where email = '" + email + "';";
	myMails = db.query(statement);

	cout << "My Mails (You have " << myMails.size() << " mail(s))" << endl;
	cout << "-----------------------------------" << endl << endl;

	for (int i = 0; i < myMails.size(); i++) {

		cout << "Mail id." << myMails[i][0] << endl
			 << "----------" << endl;

		cout << myMails[i][1] << endl << endl;
	}
}

void Student::deleteMails () {

	string mailID;
	bool exist = false;

	cout << "Enter the mail id you wish to delete (0 to delete all): ";
	cin >> mailID;
	cin.clear();

	if ( mailID == "0") {
		string statement = "DELETE FROM EMAILS WHERE email = '";
		statement += email + "';";
		db.query(statement);
		cout << endl << "All mail successfully deleted" << endl;
	}
	else {

		exist = checkMail(mailID);
		if (exist == true) {
			string statement = "DELETE FROM EMAILS WHERE mail_id = ";
			statement += mailID + ";";
			db.query(statement);
			cout << endl << "Mail successfully deleted" << endl;
		}
		else
			cout << endl << "Mail does not exist" << endl;
	}
}

bool Student::checkMail (string mailID) {

	vector < vector <string> > mailList;
	string statement = "SELECT * FROM EMAILS WHERE ";
	statement += "mail_id = " + mailID + ";";

	mailList = db.query(statement);

	if (mailList.size() == 0)
		return 0;
	else 
		return 1;
}